﻿using System;
using Accountant.DataModel;
using FluentAssertions;
using NUnit.Framework;

namespace UnitTests
{
  [TestFixture]
  public class ContextPropagation
  {
    [Test]
    public void AddingAccountToTheContainerSetGivesItAContext()
    {
      _bound.Context.Should().BeSameAs(_ctx);
    }
    [Test]
    public void RemovingAccountFromTheContainerShouldRemoveContext()
    {
      Action action = () => _ctx.Accounts.Remove(_bound);
      action.ShouldThrow<NotImplementedException>();
      // account.Context.Should().BeNull();
    }
    [Test]
    public void AddingAccountToTheContainerAttachesDerivedAccounts()
    {
      var derivedDerived = new Account { Name = "Derived Derived" };
      var derived = new Account { Name = "Derived", DerivedAccounts = { derivedDerived } };
      var account = new Account {Name = "Base", DerivedAccounts = {derived}};
      _ctx.Accounts.Add(account);
      derivedDerived.Context.Should().BeSameAs(_ctx);
      derived.Context.Should().BeSameAs(_ctx);
    }
    [Test]
    public void AddingAccountToTheContainerAttachesBaseAccounts()
    {
      var bse = new Account { Name = "Base" };
      var baseBase = new Account { Name = "Base", BaseAccount = bse };
      _ctx.Accounts.Add(new Account { Name = "Derived", BaseAccount = baseBase });
      bse.Context.Should().BeSameAs(_ctx);
      baseBase.Context.Should().BeSameAs(_ctx);
    }

    #region ' Setup '

    [SetUp]
    public void SetUp()
    {
      AccountantContext.CleanUnboundContext();
      _ctx = new AccountantContext();
      _bound = _ctx.Accounts.Add(new Account());
      _unbound = new Account();
    }

    private AccountantContext _ctx;
    private Account _bound;
    private Account _unbound;

    #endregion

    [Test]
    public void SetBaseAccountBoundToUnbound()
    {
      _unbound.BaseAccount = _bound;
      _unbound.Context.Should().Be(AccountantContext.Unbound);
      _bound.Context.Should().Be(_ctx);
    }
    [Test]
    public void SetBaseAccountUnboundToBound()
    {
      _bound.BaseAccount = _unbound;
      _bound.Context.Should().Be(_ctx);
      _unbound.Context.Should().Be(_ctx);
    }
    [Test]
    public void AddDerivedAccountBoundToUnbound()
    {
      _unbound.DerivedAccounts.Add(_bound);
      _unbound.Context.Should().Be(AccountantContext.Unbound);
      _bound.Context.Should().Be(_ctx);
    }
    [Test]
    public void AddDerivedAccountUnboundToBound()
    {
      _bound.DerivedAccounts.Add(_unbound);
      _bound.Context.Should().Be(_ctx);
      _unbound.Context.Should().Be(_ctx);
    }
  }
}